package pub.pjoc.util.reflect;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.Map;

/**
 * @author xiongyingqi
 * @since 16-11-30 下午7:38
 */
public abstract class ReflectionUtils {
  private static final Logger logger = LoggerFactory.getLogger(ReflectionUtils.class);

  public static Map<String, String> convertObjectFieldsToMap(Object o) {
    if (o == null) {
      return null;
    }

    return convertObjectFieldsToMap(o, o.getClass());
  }

  public static Map<String, String> convertObjectFieldsToMap(Object o, Class clazz) {
    if (o == null) {
      return null;
    }
    Map<String, String> map = new HashMap<String, String>();

    Field[] fields = clazz.getDeclaredFields();

    for (Field field : fields) {
      if (Modifier.isStatic(field.getModifiers())) {
        continue;
      }
      field.setAccessible(true);
      try {
        Object fieldValue = field.get(o);
        String name = field.getName();
        String fieldValueString = null;
        if (fieldValue != null) {
          fieldValueString = fieldValue.toString();
        }

        map.put(name, fieldValueString);
      } catch (IllegalAccessException e) {
        logger.error("", e);
      }
    }

    if (logger.isDebugEnabled()) {
      logger.debug("Convert object: {} to map: {}", o, map);
    }

    return map;
  }

  public static Method findGetMethod(Field field) throws NoSuchMethodException {
    if (field == null) {
      return null;
    }
    Class<?> declaringClass = field.getDeclaringClass();

    String name = field.getName();
    String suffix = name.substring(0, 1).toUpperCase();
    if (name.length() > 1) {
      suffix += name.substring(1);
    }
    String methodName = "get" + suffix;
    try {
      return declaringClass.getDeclaredMethod(methodName);
    } catch (NoSuchMethodException e) {
      if (field.getType() == Boolean.TYPE) {
        if (name.startsWith("is")) {
          return declaringClass.getDeclaredMethod(name);
        }
        methodName = "is" + suffix;
        return declaringClass.getDeclaredMethod(methodName);
      }
      throw e;
    }
  }

  public static Object getFieldValue(Field field, Object instance) throws IllegalAccessException {
    field.setAccessible(true);
    return field.get(instance);
  }

}
